library(tidyverse)
library(lubridate)
library(plotly)
library(ggrepel)
df <- read_csv("covid_19_clean_complete.csv")
Parsed with column specification:
cols(
`Province/State` = col_character(),
`Country/Region` = col_character(),
Lat = col_double(),
Long = col_double(),
Date = col_character(),
Confirmed = col_double(),
Deaths = col_double(),
Recovered = col_double()
)
pop <- read.csv("API_SP.POP.TOTL_DS2_en_csv_v2_936048.csv")
pop <- tibble(country = pop$Country.Name, pop = pop$X2018)
tests <- read_csv("full-list-covid-19-tests-per-day.csv") %>%
mutate(tests = `Daily change in cumulative total tests`)
Parsed with column specification:
cols(
Entity = col_character(),
Code = col_character(),
Date = col_character(),
`Daily change in cumulative total tests` = col_double()
)
options(scipen=999)
covid = df %>%
mutate(Date = mdy(Date)) %>%
group_by(`Country/Region`, Date) %>%
summarise(Confirmed = sum(Confirmed, na.rm = T),
Deaths = sum(Deaths, na.rm = T),
Recovered = sum(Recovered, na.rm = T)) %>%
arrange(`Country/Region`, Date)
final = covid %>%
group_by(`Country/Region`) %>%
filter(Confirmed >= 100) %>%
mutate(hunfirst = if_else( Date == min(Date), 1, 0),
days_since_hun = row_number(),
marginal_confirmed = Confirmed - lag(Confirmed)) %>%
left_join( pop %>%
mutate(country = case_when(
country == "United States" ~ "US",
country == "Korea, Rep." ~ "South Korea",
TRUE ~ as.character(country))),
by = c("Country/Region" = "country")) %>%
drop_na() %>%
mutate(confirmed_permil = Confirmed/pop*1000000,
deaths_permil = Deaths/pop*1000000,
marginal_confirmed_permil = confirmed_permil - lag(confirmed_permil)) %>%
left_join(tests %>%
mutate(Date = mdy(Date),
Entity = if_else(Entity == "United States", "US", Entity)) %>%
select(Entity, Date, tests), by = c("Country/Region" = "Entity", "Date"))
final = final %>%
left_join(final %>%
filter(confirmed_permil >= 20) %>%
group_by(`Country/Region`) %>%
mutate(days_sinc_twcon = row_number()))
Joining, by = c("Country/Region", "Date", "Confirmed", "Deaths", "Recovered", "hunfirst", "days_since_hun", "marginal_confirmed", "pop", "confirmed_permil", "deaths_permil", "marginal_confirmed_permil", "tests")
write_csv(final, "covid_final.csv")
graph_confirmed = final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_since_hun, y = Confirmed, color = `Country/Region`)) +
geom_line() + scale_y_log10() +
theme_minimal()
last = final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
group_by(`Country/Region`) %>%
filter(days_since_hun == max(days_since_hun))
graph = graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = Confirmed, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Confirmed cases by days since 100th case", x = "", y = "")
plotly = plotly_build(graph)
plotly$height = 900
plotly$width = 1100
plotly$sizingPolicy$defaultWidth = 1100
plotly$sizingPolicy$defaultHeight = 900
plotly
NA
graph_confirmed = final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_since_hun, y = marginal_confirmed, color = `Country/Region`)) +
geom_smooth(se=F) + scale_y_log10() +
theme_minimal()
graph = graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = marginal_confirmed, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Marginal confirmed cases by days since 100th case", x = "", y = "")
plotly = plotly_build(graph)
Transformation introduced infinite values in continuous y-axis`geom_smooth()` using method = 'loess' and formula 'y ~ x'
Removed 9 rows containing non-finite values (stat_smooth).
plotly$height = 900
plotly$width = 1100
plotly$sizingPolicy$defaultWidth = 1100
plotly$sizingPolicy$defaultHeight = 900
plotly
graph_confirmed = final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_sinc_twcon, y = confirmed_permil, color = `Country/Region`)) +
geom_line() + scale_y_log10() +
theme_minimal()
graph = graph_confirmed +
geom_text(aes(x = days_sinc_twcon + 2, y = confirmed_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Confirmed per 1M cases by days since 20th case per 1M", x = "", y = "")
plotly = plotly_build(graph)
plotly$height = 900
plotly$width = 1100
plotly$sizingPolicy$defaultWidth = 1100
plotly$sizingPolicy$defaultHeight = 900
plotly
NA
graph_confirmed = final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60) %>%
ggplot(aes(x = days_sinc_twcon, y = marginal_confirmed_permil, color = `Country/Region`)) +
geom_smooth(se=F) + scale_y_log10() +
theme_minimal()
graph = graph_confirmed +
geom_text(aes(x = days_sinc_twcon + 2, y = marginal_confirmed_permil, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "Marginal confirmed per 1M cases by days since 20th case per 1M", x = "", y = "")
plotly = plotly_build(graph)
Transformation introduced infinite values in continuous y-axis`geom_smooth()` using method = 'loess' and formula 'y ~ x'
Removed 123 rows containing non-finite values (stat_smooth).pseudoinverse used at 4neighborhood radius 2reciprocal condition number 0
plotly$height = 900
plotly$width = 1100
plotly$sizingPolicy$defaultWidth = 1100
plotly$sizingPolicy$defaultHeight = 900
plotly
NA
graph_confirmed = final %>%
filter(`Country/Region` %in% c("US", "China", "Italy", "Spain", "Germany", "France", "Israel", "Sweden", "Japan", "United Kingdom", "South Korea"),
days_since_hun < 60,
!is.na(tests)) %>%
ggplot(aes(x = days_since_hun, y = marginal_confirmed/tests, color = `Country/Region`)) +
geom_smooth(se = F) + scale_y_log10() +
theme_minimal()
graph = graph_confirmed +
geom_text(aes(x = days_since_hun + 2, y = marginal_confirmed/tests, color = `Country/Region`, label = `Country/Region`), data = last, check_overlap = TRUE) +
theme(legend.position = "none") +
labs(title = "% of tests confirmed by days since 100th confirmed", x = "", y = "")
plotly = plotly_build(graph)
Transformation introduced infinite values in continuous y-axis`geom_smooth()` using method = 'loess' and formula 'y ~ x'
Removed 3 rows containing non-finite values (stat_smooth).
plotly$height = 900
plotly$width = 1200
plotly$sizingPolicy$defaultWidth = 1200
plotly$sizingPolicy$defaultHeight = 900
plotly
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQotLS0KdGl0bGU6ICJSIE5vdGVib29rIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGdncmVwZWwpCmRmIDwtIHJlYWRfY3N2KCJjb3ZpZF8xOV9jbGVhbl9jb21wbGV0ZS5jc3YiKQpwb3AgPC0gcmVhZC5jc3YoIkFQSV9TUC5QT1AuVE9UTF9EUzJfZW5fY3N2X3YyXzkzNjA0OC5jc3YiKQpwb3AgPC0gdGliYmxlKGNvdW50cnkgPSBwb3AkQ291bnRyeS5OYW1lLCBwb3AgPSBwb3AkWDIwMTgpCnRlc3RzIDwtIHJlYWRfY3N2KCJmdWxsLWxpc3QtY292aWQtMTktdGVzdHMtcGVyLWRheS5jc3YiKSAlPiUKICBtdXRhdGUodGVzdHMgPSBgRGFpbHkgY2hhbmdlIGluIGN1bXVsYXRpdmUgdG90YWwgdGVzdHNgKQpvcHRpb25zKHNjaXBlbj05OTkpCmBgYAoKCmBgYHtyfQpjb3ZpZCA9IGRmICU+JQogIG11dGF0ZShEYXRlID0gbWR5KERhdGUpKSAlPiUKICBncm91cF9ieShgQ291bnRyeS9SZWdpb25gLCBEYXRlKSAlPiUKICBzdW1tYXJpc2UoQ29uZmlybWVkID0gc3VtKENvbmZpcm1lZCwgbmEucm0gPSBUKSwKICAgICAgICAgICAgRGVhdGhzID0gc3VtKERlYXRocywgbmEucm0gPSBUKSwKICAgICAgICAgICAgUmVjb3ZlcmVkID0gc3VtKFJlY292ZXJlZCwgbmEucm0gPSBUKSkgJT4lCiAgYXJyYW5nZShgQ291bnRyeS9SZWdpb25gLCBEYXRlKQoKCmZpbmFsID0gY292aWQgJT4lCiAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCkgJT4lCiAgZmlsdGVyKENvbmZpcm1lZCA+PSAxMDApICU+JQogIG11dGF0ZShodW5maXJzdCA9IGlmX2Vsc2UoIERhdGUgPT0gbWluKERhdGUpLCAxLCAwKSwKICAgICAgICAgZGF5c19zaW5jZV9odW4gPSByb3dfbnVtYmVyKCksCiAgICAgICAgIG1hcmdpbmFsX2NvbmZpcm1lZCA9IENvbmZpcm1lZCAtIGxhZyhDb25maXJtZWQpKSAlPiUKICBsZWZ0X2pvaW4oIHBvcCAlPiUKICAgICAgICAgICAgICAgbXV0YXRlKGNvdW50cnkgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgY291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyIgfiAiVVMiLAogICAgICAgICAgICAgICAgIGNvdW50cnkgPT0gIktvcmVhLCBSZXAuIiB+ICJTb3V0aCBLb3JlYSIsCiAgICAgICAgICAgICAgICAgVFJVRSB+IGFzLmNoYXJhY3Rlcihjb3VudHJ5KSkpLCAKICAgICAgICAgICAgIGJ5ID0gYygiQ291bnRyeS9SZWdpb24iID0gImNvdW50cnkiKSkgJT4lCiAgZHJvcF9uYSgpICU+JQogIG11dGF0ZShjb25maXJtZWRfcGVybWlsID0gQ29uZmlybWVkL3BvcCoxMDAwMDAwLAogICAgICAgICBkZWF0aHNfcGVybWlsID0gRGVhdGhzL3BvcCoxMDAwMDAwLAogICAgICAgICBtYXJnaW5hbF9jb25maXJtZWRfcGVybWlsID0gY29uZmlybWVkX3Blcm1pbCAtIGxhZyhjb25maXJtZWRfcGVybWlsKSkgJT4lCiAgbGVmdF9qb2luKHRlc3RzICU+JQogICAgICAgICAgICAgIG11dGF0ZShEYXRlID0gbWR5KERhdGUpLAogICAgICAgICAgICAgICAgICAgICBFbnRpdHkgPSBpZl9lbHNlKEVudGl0eSA9PSAiVW5pdGVkIFN0YXRlcyIsICJVUyIsIEVudGl0eSkpICU+JQogICAgICAgICAgICAgIHNlbGVjdChFbnRpdHksIERhdGUsIHRlc3RzKSwgYnkgPSBjKCJDb3VudHJ5L1JlZ2lvbiIgPSAiRW50aXR5IiwgIkRhdGUiKSkKCgpmaW5hbCA9IGZpbmFsICU+JQogIGxlZnRfam9pbihmaW5hbCAlPiUKICAgICAgICAgICAgICBmaWx0ZXIoY29uZmlybWVkX3Blcm1pbCA+PSAyMCkgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkoYENvdW50cnkvUmVnaW9uYCkgJT4lCiAgICAgICAgICAgICAgbXV0YXRlKGRheXNfc2luY190d2NvbiA9IHJvd19udW1iZXIoKSkpCgp3cml0ZV9jc3YoZmluYWwsICJjb3ZpZF9maW5hbC5jc3YiKQogIAoKYGBgCgoKCgoKCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkID0gZmluYWwgJT4lCiAgZmlsdGVyKGBDb3VudHJ5L1JlZ2lvbmAgJWluJSBjKCJVUyIsICJDaGluYSIsICJJdGFseSIsICJTcGFpbiIsICJHZXJtYW55IiwgIkZyYW5jZSIsICJJc3JhZWwiLCAiU3dlZGVuIiwgIkphcGFuIiwgIlVuaXRlZCBLaW5nZG9tIiwgIlNvdXRoIEtvcmVhIiksCiAgICAgICAgIGRheXNfc2luY2VfaHVuIDwgNjApICU+JQogIGdncGxvdChhZXMoeCA9IGRheXNfc2luY2VfaHVuLCB5ID0gQ29uZmlybWVkLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fbGluZSgpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgdGhlbWVfbWluaW1hbCgpIAogIAoKbGFzdCA9IGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgYygiVVMiLCAiQ2hpbmEiLCAiSXRhbHkiLCAiU3BhaW4iLCAiR2VybWFueSIsICJGcmFuY2UiLCAiSXNyYWVsIiwgIlN3ZWRlbiIsICJKYXBhbiIsICJVbml0ZWQgS2luZ2RvbSIsICJTb3V0aCBLb3JlYSIpLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBncm91cF9ieShgQ291bnRyeS9SZWdpb25gKSAlPiUKICBmaWx0ZXIoZGF5c19zaW5jZV9odW4gPT0gbWF4KGRheXNfc2luY2VfaHVuKSkKCmdyYXBoID0gZ3JhcGhfY29uZmlybWVkICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZGF5c19zaW5jZV9odW4gKyAyLCB5ID0gQ29uZmlybWVkLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIkNvbmZpcm1lZCBjYXNlcyBieSBkYXlzIHNpbmNlIDEwMHRoIGNhc2UiLCB4ID0gIiIsIHkgPSAiIikKCgogIAogIApwbG90bHkgPSBwbG90bHlfYnVpbGQoZ3JhcGgpCnBsb3RseSRoZWlnaHQgPSA5MDAKcGxvdGx5JHdpZHRoID0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRXaWR0aCA9IDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0SGVpZ2h0ID0gOTAwCnBsb3RseQogCmBgYAoKCgoKYGBge3J9CmdyYXBoX2NvbmZpcm1lZCA9IGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgYygiVVMiLCAiQ2hpbmEiLCAiSXRhbHkiLCAiU3BhaW4iLCAiR2VybWFueSIsICJGcmFuY2UiLCAiSXNyYWVsIiwgIlN3ZWRlbiIsICJKYXBhbiIsICJVbml0ZWQgS2luZ2RvbSIsICJTb3V0aCBLb3JlYSIpLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNlX2h1biwgeSA9IG1hcmdpbmFsX2NvbmZpcm1lZCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gKSkgKyAKICBnZW9tX3Ntb290aChzZT1GKSArIHNjYWxlX3lfbG9nMTAoKSArIAogIHRoZW1lX21pbmltYWwoKSAKICAKCgpncmFwaCA9IGdyYXBoX2NvbmZpcm1lZCArIAogIGdlb21fdGV4dChhZXMoeCA9IGRheXNfc2luY2VfaHVuICsgMiwgeSA9IG1hcmdpbmFsX2NvbmZpcm1lZCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gLCBsYWJlbCA9IGBDb3VudHJ5L1JlZ2lvbmApLCBkYXRhID0gbGFzdCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIAogIGxhYnModGl0bGUgPSAiTWFyZ2luYWwgY29uZmlybWVkIGNhc2VzIGJ5IGRheXMgc2luY2UgMTAwdGggY2FzZSIsIHggPSAiIiwgeSA9ICIiKQoKCiAgCiAgCnBsb3RseSA9IHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA9IDkwMApwbG90bHkkd2lkdGggPSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdFdpZHRoID0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPSA5MDAKcGxvdGx5CmBgYAoKCgoKCmBgYHtyfQpncmFwaF9jb25maXJtZWQgPSBmaW5hbCAlPiUKICBmaWx0ZXIoYENvdW50cnkvUmVnaW9uYCAlaW4lIGMoIlVTIiwgIkNoaW5hIiwgIkl0YWx5IiwgIlNwYWluIiwgIkdlcm1hbnkiLCAiRnJhbmNlIiwgIklzcmFlbCIsICJTd2VkZW4iLCAiSmFwYW4iLCAiVW5pdGVkIEtpbmdkb20iLCAiU291dGggS29yZWEiKSwKICAgICAgICAgZGF5c19zaW5jZV9odW4gPCA2MCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF5c19zaW5jX3R3Y29uLCB5ID0gY29uZmlybWVkX3Blcm1pbCwgY29sb3IgPSBgQ291bnRyeS9SZWdpb25gKSkgKyAKICBnZW9tX2xpbmUoKSArIHNjYWxlX3lfbG9nMTAoKSArIAogIHRoZW1lX21pbmltYWwoKSAKICAKCgpncmFwaCA9IGdyYXBoX2NvbmZpcm1lZCArIAogIGdlb21fdGV4dChhZXMoeCA9IGRheXNfc2luY190d2NvbiArIDIsIHkgPSBjb25maXJtZWRfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmAsIGxhYmVsID0gYENvdW50cnkvUmVnaW9uYCksIGRhdGEgPSBsYXN0LCBjaGVja19vdmVybGFwID0gVFJVRSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgCiAgbGFicyh0aXRsZSA9ICJDb25maXJtZWQgcGVyIDFNIGNhc2VzIGJ5IGRheXMgc2luY2UgMjB0aCBjYXNlIHBlciAxTSIsIHggPSAiIiwgeSA9ICIiKQoKCiAgCiAgCnBsb3RseSA9IHBsb3RseV9idWlsZChncmFwaCkKcGxvdGx5JGhlaWdodCA9IDkwMApwbG90bHkkd2lkdGggPSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdFdpZHRoID0gMTEwMApwbG90bHkkc2l6aW5nUG9saWN5JGRlZmF1bHRIZWlnaHQgPSA5MDAKcGxvdGx5CiAKYGBgCgoKYGBge3J9CmdyYXBoX2NvbmZpcm1lZCA9IGZpbmFsICU+JQogIGZpbHRlcihgQ291bnRyeS9SZWdpb25gICVpbiUgYygiVVMiLCAiQ2hpbmEiLCAiSXRhbHkiLCAiU3BhaW4iLCAiR2VybWFueSIsICJGcmFuY2UiLCAiSXNyYWVsIiwgIlN3ZWRlbiIsICJKYXBhbiIsICJVbml0ZWQgS2luZ2RvbSIsICJTb3V0aCBLb3JlYSIpLAogICAgICAgICBkYXlzX3NpbmNlX2h1biA8IDYwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXlzX3NpbmNfdHdjb24sIHkgPSBtYXJnaW5hbF9jb25maXJtZWRfcGVybWlsLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fc21vb3RoKHNlPUYpICsgc2NhbGVfeV9sb2cxMCgpICsgCiAgdGhlbWVfbWluaW1hbCgpIAogIAoKCmdyYXBoID0gZ3JhcGhfY29uZmlybWVkICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZGF5c19zaW5jX3R3Y29uICsgMiwgeSA9IG1hcmdpbmFsX2NvbmZpcm1lZF9wZXJtaWwsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCwgbGFiZWwgPSBgQ291bnRyeS9SZWdpb25gKSwgZGF0YSA9IGxhc3QsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIk1hcmdpbmFsIGNvbmZpcm1lZCBwZXIgMU0gY2FzZXMgYnkgZGF5cyBzaW5jZSAyMHRoIGNhc2UgcGVyIDFNIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5ID0gcGxvdGx5X2J1aWxkKGdyYXBoKQpwbG90bHkkaGVpZ2h0ID0gOTAwCnBsb3RseSR3aWR0aCA9IDExMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPSAxMTAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdEhlaWdodCA9IDkwMApwbG90bHkKIApgYGAKCgoKCgoKCgpgYGB7cn0KZ3JhcGhfY29uZmlybWVkID0gZmluYWwgJT4lCiAgZmlsdGVyKGBDb3VudHJ5L1JlZ2lvbmAgJWluJSBjKCJVUyIsICJDaGluYSIsICJJdGFseSIsICJTcGFpbiIsICJHZXJtYW55IiwgIkZyYW5jZSIsICJJc3JhZWwiLCAiU3dlZGVuIiwgIkphcGFuIiwgIlVuaXRlZCBLaW5nZG9tIiwgIlNvdXRoIEtvcmVhIiksCiAgICAgICAgIGRheXNfc2luY2VfaHVuIDwgNjAsCiAgICAgICAgICFpcy5uYSh0ZXN0cykpICU+JQogIGdncGxvdChhZXMoeCA9IGRheXNfc2luY2VfaHVuLCB5ID0gbWFyZ2luYWxfY29uZmlybWVkL3Rlc3RzLCBjb2xvciA9IGBDb3VudHJ5L1JlZ2lvbmApKSArIAogIGdlb21fc21vb3RoKHNlID0gRikgKyBzY2FsZV95X2xvZzEwKCkgKyAKICB0aGVtZV9taW5pbWFsKCkgCiAgCgoKZ3JhcGggPSBncmFwaF9jb25maXJtZWQgKyAKICBnZW9tX3RleHQoYWVzKHggPSBkYXlzX3NpbmNlX2h1biArIDIsIHkgPSBtYXJnaW5hbF9jb25maXJtZWQvdGVzdHMsIGNvbG9yID0gYENvdW50cnkvUmVnaW9uYCwgbGFiZWwgPSBgQ291bnRyeS9SZWdpb25gKSwgZGF0YSA9IGxhc3QsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBsYWJzKHRpdGxlID0gIiUgb2YgdGVzdHMgY29uZmlybWVkIGJ5IGRheXMgc2luY2UgMTAwdGggY29uZmlybWVkIiwgeCA9ICIiLCB5ID0gIiIpCgoKICAKICAKcGxvdGx5ID0gcGxvdGx5X2J1aWxkKGdyYXBoKQpwbG90bHkkaGVpZ2h0ID0gOTAwCnBsb3RseSR3aWR0aCA9IDEyMDAKcGxvdGx5JHNpemluZ1BvbGljeSRkZWZhdWx0V2lkdGggPSAxMjAwCnBsb3RseSRzaXppbmdQb2xpY3kkZGVmYXVsdEhlaWdodCA9IDkwMApwbG90bHkKYGBgCgoKCgoKCgoKCgoKCgoKCgoKCgo=